######## RANNEY UPDATE ###########
######## LAUREN FUTTER ###########
########## 7/21/25 ###############

install.packages(c("dplyr","cspp"))
install.packages("tidyr")
install.packages("zoo")
install.packages("slider")
library(dplyr)
library(tidyr)
library(haven)
library(zoo)
library(slider)
 
remotes::install_github("ropensci/tabulizer")

library(tabulapdf)


setwd("Replication Files")

#To construct the Ranney index we need
#1. Percentage of the popular vote for gubernatorial candidates (by Democrats)
#2. Proportion of seats in the lower legislative chamber under Democratic control
#3. Proportion of seats in the upper chamber under Democratic control
#4. Percentage of time both the governorship and legislative majorities are held by Democrats


#1. Percentage of the popular vote for gubernatorial candidates (by Democrats)

#Load data from CQ
gub_vote_tot1 <- read.csv("Gub_Vote_Totals_2011_2020.csv")
gub_vote_tot2 <- read.csv("Gub_Vote_Totals_2021_2024.csv")

gub_vote_tot <- rbind(gub_vote_tot1, gub_vote_tot2)
gub_vote_tot$year <- substr(as.character(gub_vote_tot$raceYear), 1, 4)




#2. Proportion of seats in the lower legislative chamber under Democratic control


#Save merged data
legis_control_merge <- readRDS("legis_control_merge")

#Senate Dem Proportion
legis_control_merge$ranney1_sen_dem_prop <- legis_control_merge$Sen.Dem.Prop

#Senate House Proportion
legis_control_merge$ranney2_hs_dem_prop <- legis_control_merge$House.Dem.Prop

#Gubernatorial Democrat Votes
legis_control_merge <- legis_control_merge %>%
  arrange(State, Year) %>%
  group_by(State) %>%
  mutate(ranney3_gub_prop = DemVotesMajorPercent) %>%
  fill(ranney3_gub_prop, .direction = "down") %>%
  ungroup()

legis_control_merge$ranney3_gub_prop <- legis_control_merge$ranney3_gub_prop/100
legis_control_merge$ranney4_control <- ifelse(legis_control_merge$State.Control == "Rep",0,ifelse(legis_control_merge$State.Control == "Dem",1,.5))

#Get rid of any asterisks
legis_control_merge <- legis_control_merge %>%
  mutate(across(everything(), ~ gsub("\\*", "", as.character(.))))

#Subset the data 
legis_control_merge_subset <- legis_control_merge %>% select(State, Year, ranney1_sen_dem_prop, ranney2_hs_dem_prop,ranney3_gub_prop, ranney4_control)
legis_control_merge_subset$State[legis_control_merge_subset$State == "Connecticut*"] <- "Connecticut"
legis_control_merge_subset$State[legis_control_merge_subset$State == "New York*"] <- "New York"
legis_control_merge_subset$State[legis_control_merge_subset$State == "Alaska*"] <- "Alaska"
legis_control_merge_subset$State[legis_control_merge_subset$State == "Vermont*"] <- "Vermont"

saveRDS(legis_control_merge_subset,"legis_control_merge_subset")

#Subset Ranney data
ranney <- read.table("Ranney_HVD_From_Klarner_2013_04_08.tab",sep="\t", header=TRUE)
ranney_subset <- ranney %>% select(state_name, elect_year, ranney1_sen_dem_prop, 
                                   ranney2_hs_dem_prop,ranney3_gub_prop, ranney4_control) %>%
  filter(elect_year <= 2010)

names(ranney_subset) <- c("State", "Year","ranney1_sen_dem_prop", "ranney2_hs_dem_prop", "ranney3_gub_prop", "ranney4_control")



#Bind legis_control_merge and ranney subset 
lc_ranney_bind <- rbind(ranney_subset, legis_control_merge_subset)

#Gubernatorial Democrat Votes
lc_ranney_bind <- lc_ranney_bind %>%
  arrange(State, Year) %>%
  group_by(State) %>%
  fill(ranney3_gub_prop, .direction = "down") %>%
  ungroup()

lc_ranney_bind$ranney1_sen_dem_prop <- as.numeric(lc_ranney_bind$ranney1_sen_dem_prop)
lc_ranney_bind$ranney2_hs_dem_prop <- as.numeric(lc_ranney_bind$ranney2_hs_dem_prop)
lc_ranney_bind$ranney3_gub_prop <- as.numeric(lc_ranney_bind$ranney3_gub_prop)
lc_ranney_bind$ranney4_control <- as.numeric(lc_ranney_bind$ranney4_control)

lc_ranney_bind <- lc_ranney_bind %>%
  arrange(State, Year) %>%
  group_by(State) %>%
  mutate(
    ranney1_sen_dem_prop_4yr = zoo::rollmean(ranney1_sen_dem_prop, k = 4, fill = NA, align = "right"),
    ranney1_sen_dem_prop_6yr = zoo::rollmean(ranney1_sen_dem_prop, k = 6, fill = NA, align = "right"),
    ranney1_sen_dem_prop_8yr = zoo::rollmean(ranney1_sen_dem_prop, k = 8, fill = NA, align = "right"),
    ranney1_sen_dem_prop_10yr = zoo::rollmean(ranney1_sen_dem_prop, k = 10, fill = NA, align = "right"),
    ranney2_hs_dem_prop_4yr = zoo::rollmean(ranney2_hs_dem_prop, k = 4, fill = NA, align = "right"),
    ranney2_hs_dem_prop_6yr = zoo::rollmean(ranney2_hs_dem_prop, k = 6, fill = NA, align = "right"),
    ranney2_hs_dem_prop_8yr = zoo::rollmean(ranney2_hs_dem_prop, k = 8, fill = NA, align = "right"),
    ranney2_hs_dem_prop_10yr = zoo::rollmean(ranney2_hs_dem_prop, k = 10, fill = NA, align = "right"),
    ranney3_gub_prop_4yr = zoo::rollmean(ranney3_gub_prop, k = 4, fill = NA, align = "right"),
    ranney3_gub_prop_6yr = zoo::rollmean(ranney3_gub_prop, k = 6, fill = NA, align = "right"),
    ranney3_gub_prop_8yr = zoo::rollmean(ranney3_gub_prop, k = 8, fill = NA, align = "right"),
    ranney3_gub_prop_10yr = zoo::rollmean(ranney3_gub_prop, k = 10, fill = NA, align = "right"),
    ranney4_control_4yr = zoo::rollmean(ranney4_control, k = 4, fill = NA, align = "right"),
    ranney4_control_6yr = zoo::rollmean(ranney4_control, k = 6, fill = NA, align = "right"),
    ranney4_control_8yr = zoo::rollmean(ranney4_control, k = 8, fill = NA, align = "right"),
    ranney4_control_10yr = zoo::rollmean(ranney4_control, k = 10, fill = NA, align = "right")
  ) %>%
  ungroup()


#Create Ranney Indices

lc_ranney_bind <- lc_ranney_bind %>%
  mutate(
    ranney_4yrs = rowMeans(select(., ranney1_sen_dem_prop_4yr,
                                       ranney2_hs_dem_prop_4yr,
                                       ranney3_gub_prop_4yr,
                                       ranney4_control_4yr), na.rm = TRUE),
    
    ranney_6yrs = rowMeans(select(., ranney1_sen_dem_prop_6yr,
                                       ranney2_hs_dem_prop_6yr,
                                       ranney3_gub_prop_6yr,
                                       ranney4_control_6yr), na.rm = TRUE),
    
    ranney_8yrs = rowMeans(select(., ranney1_sen_dem_prop_8yr,
                                       ranney2_hs_dem_prop_8yr,
                                       ranney3_gub_prop_8yr,
                                       ranney4_control_8yr), na.rm = TRUE),
    
    ranney_10yrs = rowMeans(select(., ranney1_sen_dem_prop_10yr,
                                        ranney2_hs_dem_prop_10yr,
                                        ranney3_gub_prop_10yr,
                                        ranney4_control_10yr), na.rm = TRUE)
  )


#Create folded Ranney
lc_ranney_bind <- lc_ranney_bind %>%
  mutate(
    folded_ranney_4yrs = 1-abs(ranney_4yrs-.5),
    folded_ranney_6yrs = 1-abs(ranney_6yrs-.5),
    folded_ranney_8yrs = 1-abs(ranney_8yrs-.5),
    folded_ranney_10yrs = 1-abs(ranney_10yrs-.5)
  )


# Create Hincliffe-Lee State Party Competition Index

lc_ranney_bind <- lc_ranney_bind %>%
  mutate(hl_index =  rowMeans(select(., ranney1_sen_dem_prop_10yr,
                                     ranney2_hs_dem_prop_10yr,
                                     ranney3_gub_prop_10yr), na.rm = TRUE)
  )

#Create HL State Party Competition Index
lc_ranney_bind <- lc_ranney_bind %>%
  mutate(folded_hl_index = 1-abs(hl_index-.5)
  )


#### Add legislative party change index ####
#Add measure of legislative control for Ranney index

ranney$Sen.Control <- ifelse(ranney$ranney1_sen_dem_prop > .5, "Dem","Rep")
ranney$House.Control <- ifelse(ranney$ranney2_hs_dem_prop > .5, "Dem","Rep")
ranney$Leg.Control <- ifelse(ranney$Sen.Control== "Dem" & ranney$House.Control=="Dem", "Dem",ifelse(ranney$Sen.Control== "Rep" & ranney$House.Control=="Rep", "Rep", "Split"))

ranney_subset2 <- ranney %>% select(state_name, elect_year, Leg.Control) %>% filter(elect_year <= 2010)
names(ranney_subset2) <- c("State", "Year","Leg.Control")

#Edit legis_control_merge
legis_control_merge$Leg.Control[legis_control_merge$Leg.Control == "Divided"] <- "Split"
legis_control_merge$Year <- as.numeric(legis_control_merge$Year)

legis_control_merge_subset <- legis_control_merge %>% select(State, Year, Leg.Control)

#Combine Ranney data and legis_control_merge to form a party switch database
party_switch <- rbind(ranney_subset2, legis_control_merge_subset)

library(slider)

# party_switch <- party_switch %>%
#   arrange(State, Year) %>%
#   group_by(State) %>%
#   mutate(
#     control_change_8yr = slide_index_dbl(
#       Leg.Control,
#       .i = Year,
#       .f = ~ sum(.x != lag(.x), na.rm = TRUE),
#       .before = 7,  # includes current year + 7 past years = 8-year window
#       .complete = TRUE
#     )
#   ) %>%
#   ungroup()


party_switch <- party_switch %>%
  arrange(State, Year, .by_group = TRUE) %>%
  group_by(State) %>%
  mutate(
    # count transitions between consecutive years in the 8-year window
    control_change_8yr = slide_index_dbl(
      .x = Leg.Control,
      .i = Year,          # must be non-decreasing within State
      .before = 7,        # current year + 7 prior rows = 8-row window
      .complete = TRUE,   # require a full 8 rows; otherwise NA
      .f = ~{
        x <- as.character(.x)
        if (length(x) < 2) return(NA_real_)
        # compare adjacent entries; NA-safe
        sum(x[-1] != x[-length(x)], na.rm = TRUE)
      }
    )
  ) %>%
  ungroup()


#Merge lc_ranney_bind and party switch
lc_ranney_bind$Year <- as.numeric(lc_ranney_bind$Year)
lcrps_merge <- left_join(lc_ranney_bind, party_switch, by = c("State","Year"))


#State legislative election returns 

#2000-2016 elections
sler <- read_dta("196slers1967to2016_20180908.dta")

sler_unique <- sler %>%
  select(sab,year, etype) %>% distinct()

sler_unique_gen <- sler_unique %>% filter(year >= 2000) %>% filter(etype == "g" | etype == "la")

sler_unique_gen$election_year <- 1

#2017-2024 elections
sler1724 <- read.csv("State_Leg_Elections_1724.csv")
sler1724 <- sler1724 %>% mutate(Election = gsub("House","", Election))
sler1724 <- sler1724 %>% mutate(Election = gsub("Senate","", Election))
sler1724 <- sler1724 %>% mutate(Election = gsub("Assembly","", Election))
sler1724 <- sler1724 %>% mutate(Election = gsub("of Representatives","", Election))
sler1724 <- sler1724 %>% mutate(Election = gsub("of Delegates","", Election))
sler1724 <- sler1724 %>% mutate(Election = gsub("State","", Election))

sler1724 <- sler1724 %>% select(year, Election) %>% distinct()
sler1724$Election <- str_trim(sler1724$Election)

sler1724$election_year <- 1

state_xwalk <- data.frame(cbind(state.name, state.abb))
names(state_xwalk) <- c("Election", "sab")

sler1724 <- left_join(sler1724,state_xwalk, by = "Election")
sler1724$sab <- tolower(sler1724$sab)

sler_unique_gen <- sler_unique_gen %>% select(sab, year, election_year)
sler1724 <- sler1724 %>% select(sab, year, election_year)

sle <- rbind(sler_unique_gen, sler1724)

saveRDS(sle, "sle")

#This is the file that contains 
#1. all Ranney indices
#2. Hinchliffe-Lee Measures
#3. Number of times party control changed in an eight year period

saveRDS(lcrps_merge, "lcrps_merge")


lcrps_merge <- readRDS("lcrps_merge")



